﻿using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

namespace _04_IOC
{
    internal class Program
    {
        static void Main(string[] args)
        {
            TestScope();
        }
        /// <summary>
        /// 容器可以解析一个容器
        /// 实现类中有一个标记指示是否为根容器
        /// </summary>
        public static void Test()
        {

            IServiceCollection services = new ServiceCollection();
            var sp = services.BuildServiceProvider();
            var sp2 = sp.GetRequiredService<IServiceProvider>();
        }
        /// <summary>
        /// 基础使用
        /// </summary>
        public static void TestBasic()
        {
            IServiceCollection services = new ServiceCollection();
            services.AddSingleton<IConnection, SqlConnection>();
            services.AddSingleton<IConnection>(sp =>
            {
                return new SqlConnection("fff");
            });            
            services.AddSingleton(typeof(SqlConnection));
            services.AddSingleton(typeof(Logger<>));
            services.AddSingleton(typeof(Logger<>).MakeGenericType(typeof(Program)));
            services.Add(new ServiceDescriptor(typeof(IConnection), typeof(SqlConnection), ServiceLifetime.Singleton));
            services.AddSingleton<IConnection, MySqlConnection>();
            services.AddSingleton<AService>();
            IServiceProvider container = services.BuildServiceProvider(new ServiceProviderOptions 
            {
                ValidateOnBuild= true,
                ValidateScopes= true,
            });
            container.GetServices<IConnection>();
            var connection = container.GetRequiredService<IConnection>();
            var service = container.GetService<AService>();
            Console.WriteLine(connection.GetType().Name);
        }
        public static void TestFactory()
        {
            IServiceCollection services = new ServiceCollection();
            services.AddSingleton(sp =>
            {
                var factory = new ConnectionFactoryBuilder()
                    .AddConnection<MySqlConnection>("mysql")
                    .AddConnection<SqlConnection>("sql")
                    .Build(sp);
                return factory;
            });
            IServiceProvider container = services.BuildServiceProvider();
            var factory = container.GetRequiredService<IConnectionFactory>();
            var connection1 = factory.CreateConnection("mysql");
            var connection2 = factory.CreateConnection("sql");
        }
        /// <summary>
        /// scope
        /// </summary>
        public static void TestScope()
        {
            var services = new ServiceCollection();
            services.AddSingleton<BService>();
            //根容器
            var rootContainer = services.BuildServiceProvider(new ServiceProviderOptions()
            {
                ValidateOnBuild = true,
                ValidateScopes = false

            });
            using (var scope = rootContainer.CreateScope())
            {
                //通过根容器创建
                var b1 = rootContainer.GetRequiredService<BService>();
                //通过子容器创建
                var b2 = scope.ServiceProvider.GetRequiredService<BService>();
                var b3 = scope.ServiceProvider.GetRequiredService<BService>();
                Console.WriteLine(b1);
                Console.WriteLine(b2);
                Console.WriteLine(b3);
            }
            //代码执行到此处，会同时释放由子容器解析出来的所有实列。
            //如果根容器被释放，则释放所有实列和子容器，以及子容器创建的实列
        }
        /// <summary>
        /// 组件扫描
        /// </summary>
        public static void TestScanner()
        {
            var services = new ServiceCollection();
            //扫描组件
            services.AddInjectionServices<Program>();
            var container = services.BuildServiceProvider();
            var logger = container.GetRequiredService<ILogger<Program>>();
            logger.Log();
            container.Dispose();//释放
        }
        /// <summary>
        /// 一个接口多个实现
        /// </summary>
        public static void TestManager()
        {
            var services = new ServiceCollection();
            services.AddTransient<IMessageProvider, EmailMessageProvider>();
            services.AddTransient<IMessageProvider, PhoneMessageProvider>();
            services.AddTransient<MessageManager>();
            var container = services.BuildServiceProvider();
            var messageManager = container.GetRequiredService<MessageManager>();
            messageManager.SendAll("fff");
            messageManager.SendPhone("666");
            messageManager.SendEmail("nb");
        }
        /// <summary>
        /// autoface
        /// </summary>
        public static void TestAutofac()
        {
            var services = new ServiceCollection();
            //微软的容器注册服务
            services.AddScoped(typeof(ILogger<>), typeof(Logger<>));
            var builder = new ContainerBuilder();
            //autofac容器注册服务
            builder.RegisterType<CService>().PropertiesAutowired()
                .As<CService>()
                .InstancePerLifetimeScope();
            builder.Populate(services);//将IServiceCollection中的服务注册到autofac
            //使用AutofacServiceProvider的实现方案，创建容器
            //加载autofac中的服务
            IServiceProvider container = new AutofacServiceProvider(builder.Build());
            var logger = container.GetRequiredService<ILogger<Program>>();
            var service = container.GetRequiredService<CService>();
        }
    }


}